享受技术带来的快乐！

不管前方的路有多远和多苦，只要走的方向是正确的，不管多么崎岖不平，都比站在原地
更接近幸福！

  • [ico_list]目录视图
  • [ico_summar]摘要视图
  • [ico_rss]订阅

CSDN专家精选，微信开发学习路线大有看头！     【博乐】点评美文，得C币     【脑洞
趴】iOS开发前沿与Swift探秘     Swift教程大汇总    

Android图片翻转动画效果

分类： Android图片处理 Android开发 Android UI 2012-10-23 10:53 1286人阅读评论
(0) 收藏举报
androidanimationlistviewtransformationfloattransition

http://blog.csdn.net/hnlshzx2008/article/details/7846621


Android中并没有提供直接做3D翻转的动画，所以关于3D翻转的动画效果需要我们自己实现
，那么我们首先来分析一下Animation 和 Transformation。

Animation动画的主要接口，其中主要定义了动画的一些属性比如开始时间，持续时间，是
否重复播放等等。而Transformation中则包含一个矩阵和alpha值，矩阵是用来做平移，旋
转和缩放动画的，而alpha值是用来做alpha动画的，要实现3D旋转动画我们需要继承自
Animation类来实现，我们需要重载 getTransformation和applyTransformation，在
getTransformation中Animation会根据动画的属性来产生一系列的差值点，然后将这些差
值点传给applyTransformation，这个函数将根据这些点来生成不同的 Transformation。
下面是具体实现：

public class Rotate3dAnimation extends Animation {
    //开始角度
    private final float mFromDegrees;
    //结束角度
    private final float mToDegrees;
    //中心点
    private final float mCenterX;
    private final float mCenterY;
    private final float mDepthZ;
    //是否需要扭曲
    private final boolean mReverse;
    //摄像头
    private Camera mCamera;
    public Rotate3dAnimation(float fromDegrees, float toDegrees,
            float centerX, float centerY, float depthZ, boolean reverse) {
        mFromDegrees = fromDegrees;
        mToDegrees = toDegrees;
        mCenterX = centerX;
        mCenterY = centerY;
        mDepthZ = depthZ;
        mReverse = reverse;
    }

    @Override
    public void initialize(int width, int height, int parentWidth, int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
        mCamera = new Camera();
    }
    //生成Transformation
    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        final float fromDegrees = mFromDegrees;
        //生成中间角度
        float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);

        final float centerX = mCenterX;
        final float centerY = mCenterY;
        final Camera camera = mCamera;

        final Matrix matrix = t.getMatrix();

        camera.save();
        if (mReverse) {
            camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
        } else {
            camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
        }
        camera.rotateY(degrees);
        //取得变换后的矩阵
        camera.getMatrix(matrix);
        camera.restore();

        matrix.preTranslate(-centerX, -centerY);
        matrix.postTranslate(centerX, centerY);
    }
}


其中包括了旋转的开始和结束角度，中心点、是否扭曲、和一个Camera，这里我们主要分
析applyTransformation函数，其中第一个参数就是通过getTransformation函数传递的差
指点，然后我们根据这个差值通过线性差值算法计算出一个中间角度degrees，Camera类是
用来实现绕Y轴旋转后透视投影的，因此我们首先通过 t.getMatrix()取得当前的矩阵，然
后通过camera.translate来对矩阵进行平移变换操作，camera.rotateY进行旋转。这样我
们就可以很轻松的实现3D旋转效果了，该例子的原意是通过一个列表来供用户选择要实现
翻转的图像，所以我们分析至少需要定义两个控件：ListView和ImageView（要翻转的图像
），主界面的xml布局定义如下所示。

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:id="@android:id/list"
        android:persistentDrawingCache="animation|scrolling"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layoutAnimation="@anim/layout_bottom_to_top_slide" />

    <ImageView
        android:id="@+id/picture"
        android:scaleType="fitCenter"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone" />

</FrameLayout>


然后准备好需要的资源，在onCreate函数中准备好 ListView和ImageView，因为要旋转所
以我们需要保存视图的缓存信息，通过 setPersistentDrawingCache
(ViewGroup.PERSISTENT_ANIMATION_CACHE);可以设置该功能，当我们选择列表中的图像资
源后在onItemClick中将选择的资源Id对应的图像设置到ImageView中，然后通过
applyRotation来启动一个动画，前面有了Rotate3dAnimation的实现，我们要完成3D翻转
动画就很简单，直接构建一个Rotate3dAnimation对象，设置其属性（包括动画监听），这
里将动画的监听设置为DisplayNextView，可以用来显示下一个视图，在其中的动画结束监
听（onAnimationEnd）中，通过一个县城SwapViews来交换两个画面，交换过程则是设置
ImageView和ListView的显示相关属性，并构建一个Rotate3dAnimation对象，对另一个界
面进行旋转即可，然后启动动画，整个转换过程实际上就是将第一个界面从0度转好90 度
，然后就爱你过第二个界面从90度转到0度，这样就形成了一个翻转动画，完整代码如下，
我们也加入了一些必要的注解，大家也可以参考APIDemo中的 Transition3d例子。

public class Transition3d extends Activity implements
        AdapterView.OnItemClickListener, View.OnClickListener {
    //照片列表
    private ListView mPhotosList;
    private ViewGroup mContainer;
    private ImageView mImageView;

    // 照片的名字，用于显示在list中
    private static final String[] PHOTOS_NAMES = new String[] {
            "Lyon",
            "Livermore",
            "Tahoe Pier",
            "Lake Tahoe",
            "Grand Canyon",
            "Bodie"
    };

    // 资源id
    private static final int[] PHOTOS_RESOURCES = new int[] {
            R.drawable.photo1,
            R.drawable.photo2,
            R.drawable.photo3,
            R.drawable.photo4,
            R.drawable.photo5,
            R.drawable.photo6
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.animations_main_screen);

        mPhotosList = (ListView) findViewById(android.R.id.list);
        mImageView = (ImageView) findViewById(R.id.picture);
        mContainer = (ViewGroup) findViewById(R.id.container);

        // 准备ListView
        final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, PHOTOS_NAMES);

        mPhotosList.setAdapter(adapter);
        mPhotosList.setOnItemClickListener(this);

        // 准备ImageView
        mImageView.setClickable(true);
        mImageView.setFocusable(true);
        mImageView.setOnClickListener(this);

        //设置需要保存缓存
        mContainer.setPersistentDrawingCache(ViewGroup.PERSISTENT_ANIMATION_CACHE);
    }

    /**
     * Setup a new 3D rotation on the container view.
     *
     * @param position the item that was clicked to show a picture, or -1 to show the list
     * @param start the start angle at which the rotation must begin
     * @param end the end angle of the rotation
     */
    private void applyRotation(int position, float start, float end) {
        // 计算中心点
        final float centerX = mContainer.getWidth() / 2.0f;
        final float centerY = mContainer.getHeight() / 2.0f;

        // Create a new 3D rotation with the supplied parameter
        // The animation listener is used to trigger the next animation
        final Rotate3dAnimation rotation =
                new Rotate3dAnimation(start, end, centerX, centerY, 310.0f, true);
        rotation.setDuration(500);
        rotation.setFillAfter(true);
        rotation.setInterpolator(new AccelerateInterpolator());
        //设置监听
        rotation.setAnimationListener(new DisplayNextView(position));

        mContainer.startAnimation(rotation);
    }

    public void onItemClick(AdapterView parent, View v, int position, long id) {
        // 设置ImageView
        mImageView.setImageResource(PHOTOS_RESOURCES[position]);
        applyRotation(position, 0, 90);
    }
    //点击图像时，返回listview
    public void onClick(View v) {
        applyRotation(-1, 180, 90);
    }

    /**
     * This class listens for the end of the first half of the animation.
     * It then posts a new action that effectively swaps the views when the container
     * is rotated 90 degrees and thus invisible.
     */
    private final class DisplayNextView implements Animation.AnimationListener {
        private final int mPosition;

        private DisplayNextView(int position) {
            mPosition = position;
        }

        public void onAnimationStart(Animation animation) {
        }
        //动画结束
        public void onAnimationEnd(Animation animation) {
            mContainer.post(new SwapViews(mPosition));
        }

        public void onAnimationRepeat(Animation animation) {
        }
    }

    /**
     * This class is responsible for swapping the views and start the second
     * half of the animation.
     */
    private final class SwapViews implements Runnable {
        private final int mPosition;

        public SwapViews(int position) {
            mPosition = position;
        }

        public void run() {
            final float centerX = mContainer.getWidth() / 2.0f;
            final float centerY = mContainer.getHeight() / 2.0f;
            Rotate3dAnimation rotation;

            if (mPosition > -1) {
                //显示ImageView
                mPhotosList.setVisibility(View.GONE);
                mImageView.setVisibility(View.VISIBLE);
                mImageView.requestFocus();

                rotation = new Rotate3dAnimation(90, 180, centerX, centerY, 310.0f, false);
            } else {
                //返回listview
                mImageView.setVisibility(View.GONE);
                mPhotosList.setVisibility(View.VISIBLE);
                mPhotosList.requestFocus();

                rotation = new Rotate3dAnimation(90, 0, centerX, centerY, 310.0f, false);
            }

            rotation.setDuration(500);
            rotation.setFillAfter(true);
            rotation.setInterpolator(new DecelerateInterpolator());
            //开始动画
            mContainer.startAnimation(rotation);
        }
    }

}



      

  • 上一篇Android视图切换的效果库 - android-viewflow
  • 下一篇Android中给图标加上数字(用于未接来电等等功能的提醒)

猜你在找

查看评论
* 以上用户言论只代表其个人观点，不代表CSDN网站的观点或立场
快速回复 TOP

    个人资料

    [1_jdsjlzx]
    jdsjlzx
      
    1
      □ 访问：2314706次
      □ 积分：30330
      □ 等级： [blog8]
        积分：30330
      □ 排名：第77名
      □ 原创：563篇
      □ 转载：1337篇
      □ 译文：6篇
      □ 评论：623条

    文章搜索

    [                    ] [搜索] 

    文章分类

  • java(120)
  • java点滴(52)
  • jsp(7)
  • 技术前瞻(7)
  • 服务器(3)
  • Android开发(1416)
  • 音乐心情(13)
  • json(7)
  • 工作点滴(49)
  • C++(21)
  • Android UI(748)
  • 书籍推荐(2)
  • Android项目(7)
  • Socket(2)
  • Android开发 qq 表情(1)
  • Android通讯录(7)
  • Android系统(116)
  • Ubuntu(31)
  • 开源工具组件(57)
  • Android优化(65)
  • Android异常处理(6)
  • Android图片处理(63)
  • Android ListView(38)
  • Android新知识(21)
  • android fragment(26)
  • Android webview(8)
  • Android优化(1)
  • Android 视频(16)
  • java串口通信(9)
  • Android 动画(15)
  • Android NDK(1)
  • Android短彩信(6)
  • Android多媒体(28)
  • Android 网络(48)
  • Android 短彩信(2)
  • Android Sqlite(7)
  • Java 网络通信(6)
  • C(3)
  • 足彩(2)
  • 程序人生(7)
  • 加密算法(2)
  • 数据结构与算法(1)
  • 理财(2)

    文章存档

  • 2015年09月(9)
  • 2015年08月(12)
  • 2015年07月(16)
  • 2015年06月(14)
  • 2015年05月(33)
  • 2015年04月(27)
  • 2015年03月(34)
  • 2015年02月(32)
  • 2015年01月(64)
  • 2014年12月(51)
  • 2014年11月(93)
  • 2014年10月(15)
  • 2014年09月(15)
  • 2014年08月(18)
  • 2014年07月(14)
  • 2014年06月(4)
  • 2014年05月(10)
  • 2014年04月(9)
  • 2014年03月(71)
  • 2014年02月(18)
  • 2014年01月(15)
  • 2013年12月(26)
  • 2013年11月(21)
  • 2013年10月(42)
  • 2013年09月(15)
  • 2013年08月(13)
  • 2013年07月(31)
  • 2013年06月(30)
  • 2013年05月(37)
  • 2013年04月(24)
  • 2013年03月(52)
  • 2013年02月(49)
  • 2013年01月(38)
  • 2012年12月(55)
  • 2012年11月(40)
  • 2012年10月(35)
  • 2012年09月(11)
  • 2012年08月(20)
  • 2012年07月(40)
  • 2012年06月(96)
  • 2012年05月(163)
  • 2012年04月(48)
  • 2012年03月(70)
  • 2012年02月(62)
  • 2012年01月(28)
  • 2011年12月(34)
  • 2011年11月(52)
  • 2011年10月(21)
  • 2011年09月(29)
  • 2011年08月(52)
  • 2011年07月(77)
  • 2011年05月(2)
  • 2011年03月(1)
  • 2011年02月(3)
  • 2011年01月(1)
  • 2010年12月(3)
  • 2010年11月(6)
  • 2010年10月(1)
  • 2010年08月(3)

    阅读排行

  • Fragment和FragmentActivity的使用方法 .(53278)
  • Android Material Design之Toolbar与Palette实践(30087)
  • android EditText自定义样式(23583)
  • Android 的不同尺寸图片和布局（手机）(20368)
  • android状态栏一体化(改变状态栏的背景颜色)开源工程推荐(20013)
  • Android搜索控件SearchView的用法(15768)
  • HttpClient通过Post上传文件(14528)
  • Android提高篇之自定义dialog实现processDialog“正在加载”效果、使用Animation实
    现图片旋转(14489)
  • android 读取本地或网络图片，转换为Bitmap -(11855)
  • Android屏幕适配全攻略(最权威的官方适配指导)(11739)

    评论排行

  • Android Material Design之Toolbar与Palette实践(35)
  • Android仿微信图片上传，可以选择多张图片，缩放预览，拍照上传等(26)
  • android状态栏一体化(改变状态栏的背景颜色)开源工程推荐(18)
  • Android自定义控件StaggeredGridView-瀑布流效果的GridView(10)
  • PinnedSectionListView：分组的listView滑动中固定组标题的实现(10)
  • Android组件——使用DrawerLayout仿网易新闻v4.4侧滑菜单(9)
  • Android屏幕适配全攻略(最权威的官方适配指导)(9)
  • Android自定义捕获Application全局异常(8)
  • Fragment和FragmentActivity的使用方法 .(8)
  • Android中图片的处理（放大缩小，去色，转换格式，增加水印等）(7)

    推荐文章

    最新评论

  • android状态栏一体化(改变状态栏的背景颜色)开源工程推荐

    xiarideyeguang: 为什么返回之后再进入这个页面，状态栏就不是一体化了

  • Android BadgeView使用介绍（数字提醒提示）

    yuan1993711: 写的很详细，学到了

  • Android Listview滑动时不加载数据，停下来时加载数据，让App更优

    Guangxingtianxia1206: 好棒！但是，我纳闷，当我用
    viewHolder.icon.setImageResource(R.mi...

  • Android AsyncHttpClient登录保存cookie和读写cookie

    qq12547345: 感谢大神的帮助，实在是解决我的燃眉之急！赞一个！

  • Eclipse如何快速修改工程名及包名

    chenqingze: @mijiong:R文件删掉，重构

  • 在Eclipse添加Android兼容包( v4、v7 appcompat )

    qq_25925537: 挺好！！！！！！！！！！！！！！

  • 在Eclipse添加Android兼容包( v4、v7 appcompat )

    qq_25925537: 不错！！！！！

  • Android 二维码扫描怎样实现第二次（重复）扫描

    wanwuyishi11: 我的也不行，希望给个demo试试，1696460086@qq.com

  • Android 用代码查看本机保存的Wifi密码

    oPINGU: 楼主，当wifi名为中文时，不会显示，有没办法解决

  • Android漂亮的UI库集合

    u011322020: 赞~
   
